我們在先前的第一個範例,有看到使用react提供的hook-useState,來當作狀態的管理。
import { useState } from "react";
function App(props) { // react傳進function component的值稱為props
const [val, setVal] = useState(0); // react的狀態宣告
const pulsOne = () => { // 自定義的程式內容
setVal(val + 1);
}
// 呈現的畫面放在return
return (
<>
<h2 id="val">{val}</h2>
<button id="btn" onClick={pulsOne}>+1</button>
</>
)
}
export default App
把useState改為一般變數試試
function App() {
let val = 0;
const pulsOne = () => {
val = val + 1;
console.log(val);
}
return (
<>
<h2 id="val">{val}</h2>
<button id="btn" onClick={pulsOne}>+1</button>
</>
)
}
export default App
結果如下圖,奇怪!console明明就有加上去,為什麼畫面還是0
這是因為沒有畫面沒有被更新,useState回傳的第2個變數提供了我們重新渲染的功能,在這邊我們先把渲染當作是重新呼叫一次這個function component,來達到更新畫面的效果。
那我們再試試如果重新渲染過後一般的變數在function component會怎樣
import { useState } from "react";
function App() {
let val = 0;
const [stateVal, setStateVal] = useState(0);
const pulsOne = () => {
// 使用setStateVal來重新渲染
setStateVal(stateVal + 1);
val = val + 1;
console.log(val);
}
return (
<>
<h2 id="val">{stateVal}</h2>
<h2 id="val">{val}</h2>
<button id="btn" onClick={pulsOne}>+1</button>
</>
)
}
export default App
得到如下結果,畫面上還是0,console是1
會有這樣的結果是因為重新渲染(重新呼叫一次function),變數也被重新宣告又賦值為0
我們可以根據上面的幾項測試了解到function component裡的useState比一般變數多了一些功能
知道了useState的功能後,這段落來說明useStat的使用細節。
const [val, setVal] = useState(0);
呼叫useState會回傳一個length為2得陣列,第0的個是變數的值(初始值為呼叫useState帶入的值),第1個則是變更變數值的setter function,這邊使用解構去接回傳的變數。
只能在function component的最上層使用
import { useState } from "react";
function App({isPass}) {
// o 只能在最外層
const [stateVal, setStateVal] = useState(0);
// x 不行條件判斷裡
if (isPass) {
const [stateVal, setStateVal] = useState(0);
}
const pulsOne = () => {
// x 不能在function裡
const [stateVal, setStateVal] = useState(0);
}
return (
<>
// x 也不能在jsx
{const [stateVal, setStateVal] = useState(0);}
<h2 id="val">{stateVal}</h2>
<h2 id="val">{val}</h2>
<button id="btn" onClick={pulsOne}>+1</button>
</>
)
}
export default App
這裡文件有特別提到,hooks不能使用條件讓hooks在某些情形的渲染是有執行,某次重新渲染又沒有執行。這是因為hooks的機制所限制。我們可以想想useState只有回傳一個array,是怎麼能記錄每次state的值,答案是依照useState的順序紀錄在每個function component各自的陣列裡,所以如果變更順序或是更改個數,這個陣列就會對照不起來發生錯誤。
每個function component的狀態是獨立的
import { useState } from "react";
function Counter(props) { // react傳進function component的值稱為props
const [val, setVal] = useState(0); // react的狀態宣告
const pulsOne = () => { // 自定義的程式內容
setVal(val + 1);
}
// 呈現的畫面放在return
return (
<>
<h2 id="val">{val}</h2>
<button id="btn" onClick={pulsOne}>+1</button>
</>
)
}
function App() {
return <>
<Counter />
<Counter />
</>
}
export default App
也就是說我們用了兩次Counter component,各自counter是各自獨立且私有的,只會+到自己的狀態
https://react.dev/learn/state-a-components-memory